﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;

namespace System
{
    public static class XmlHelper
    {
        #region OpenXml
        /// <summary>
        /// 创建一个XmlDocument对象
        /// </summary>
        /// <param name="PathOrString">文件名称或XML字符串</param>
        public static XmlDocument OpenXml(string PathOrString)
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                if (File.Exists(PathOrString))
                {
                    xDoc.Load(PathOrString);
                }
                else
                {
                    xDoc.LoadXml(PathOrString);
                }
                return xDoc;
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #endregion

        #region Format

        /// <summary>
        /// 创建一个XmlDocument对象
        /// </summary>
        /// <param name="PathOrString">文件名称或XML字符串</param>
        public static string FormatXml(string PathOrString)
        {
            try
            {
                XmlDocument xDoc = new XmlDocument();
                if (File.Exists(PathOrString))
                {
                    xDoc.Load(PathOrString);
                }
                else
                {
                    xDoc.LoadXml(PathOrString);
                }

                return FormatXml(xDoc);
            }
            catch (Exception)
            {
                return null;
            }
        }

        public static string FormatXml(XmlDocument xml)
        {
            StringBuilder sb = new StringBuilder();
            StringWriter sw = new StringWriter(sb);
            XmlTextWriter xtw = null;
            try
            {
                xtw = new XmlTextWriter(sw);
                xtw.Formatting = Formatting.Indented;
                xtw.Indentation = 1;
                xtw.IndentChar = '\t';
                xml.WriteTo(xtw);
            }
            finally
            {
                xtw?.Close();
            }
            return sb.ToString();
        }
        #endregion

        #region CreateXMLFile
        /// <summary>
        /// 创建一个XML文档
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="rootName">根结点名称</param>
        /// <param name="elemName">元素节点名称</param>
        /// <param name="paras">XML参数</param>
        public static void CreateXMLFile(string fileFullName, string rootName, string elemName, params XmlParameter[] paras)
        {
            XmlDocument xDoc = new XmlDocument();
            XmlNode xn;
            xn = xDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
            xDoc.AppendChild(xn);
            XmlNode root = xDoc.CreateElement(rootName);
            xDoc.AppendChild(root);
            XmlNode ln = xDoc.CreateNode(XmlNodeType.Element, elemName, null);
            AppendChild(xDoc, ln, paras);
            root.AppendChild(ln);
            try
            {
                xDoc.Save(fileFullName);
            }
            catch
            {
                throw;
            }
        }
        /// <summary>
        /// 创建一个XML文档
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="rootName">根结点名称</param>
        /// <param name="elemp">元素节点对象</param>
        /// <param name="paras">XML参数</param>
        public static void CreateXMLFile(string fileFullName, string rootName, XmlParameter elemp, params XmlParameter[] paras)
        {
            XmlDocument xDoc = new XmlDocument();
            XmlNode xn;
            xn = xDoc.CreateXmlDeclaration("1.0", "UTF-8", null);
            xDoc.AppendChild(xn);
            XmlNode root = xDoc.CreateElement(rootName);
            xDoc.AppendChild(root);
            XmlNode ln = xDoc.CreateNode(XmlNodeType.Element, elemp.Name, null);
            ln.InnerText = elemp.InnerText;
            string ns = elemp.NamespaceOfPrefix == null ? "" : ln.GetNamespaceOfPrefix(elemp.NamespaceOfPrefix);
            if (elemp.Attributes?.Length > 0)
            {
                foreach (AttributeParameter ap in elemp.Attributes)
                {
                    XmlNode elemAtt = xDoc.CreateNode(XmlNodeType.Attribute, ap.Name, ns == "" ? null : ns);
                    elemAtt.Value = ap.Value;
                    ln.Attributes.SetNamedItem(elemAtt);
                }
            }
            AppendChild(xDoc, ln, paras);
            root.AppendChild(ln);
            try
            {
                xDoc.Save(fileFullName);
            }
            catch
            {
                throw;
            }
        }
        #endregion

        #region AddNewNode
        /// <summary>
        /// 添加新节点
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="parentNode">新节点的父节点对象</param>
        /// <param name="paras">XML参数对象</param>
        public static bool AddNewNode(string fileFullName, XmlNode parentNode, params XmlParameter[] paras)
        {
            return AddNewNode(fileFullName, parentNode.Name, paras);
        }

        /// <summary>
        /// 添加新节点
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="parentName">新节点的父节点名称</param>
        /// <param name="paras">XML参数对象</param>
        public static bool AddNewNode(string fileFullName, string parentName, params XmlParameter[] paras)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            XmlNode parentNode = xDoc.GetNode(parentName);
            if (parentNode == null) 
                return false;
            if (parentNode.Name == xDoc.DocumentElement.Name)
            {
                XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, parentName, null);
                AppendChild(xDoc, newNode, paras);
                xDoc.DocumentElement.AppendChild(newNode);
            }
            else
            {
                AddEveryNode(xDoc, parentNode, paras);
            }
            xDoc.Save(fileFullName);
            return true;
        }

        /// <summary>
        /// 添加新节点
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="parentName">新节点的父节点名称</param>
        /// <param name="paras">XML参数对象</param>
        public static bool AddNewNode(this XmlDocument xDoc, string parentName, params XmlParameter[] paras)
        {
            XmlNode parentNode = xDoc.GetNode(parentName);
            if (parentNode == null)
                return false;
            return xDoc.AddNewNode(parentNode, paras);
        }

        /// <summary>
        /// 添加新节点
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="parentNode">新节点的父节点对象</param>
        /// <param name="paras">XML参数对象</param>
        public static bool AddNewNode(this XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] paras)
        {
            if (parentNode.Name == xDoc.DocumentElement.Name)
            {
                XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, parentNode.Name, null);
                AppendChild(xDoc, newNode, paras);
                xDoc.DocumentElement.AppendChild(newNode);
            }
            else
            {
                AddEveryNode(xDoc, parentNode, paras);
            }
            return true;
        }
        #endregion

        #region AddAttribute
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="node">节点对象</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attributeName">新属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void AddAttribute(this XmlDocument xDoc, XmlNode node, string namespaceOfPrefix, string attributeName, string attributeValue)
        {
            string ns = namespaceOfPrefix == null ? null : node.GetNamespaceOfPrefix(namespaceOfPrefix);
            XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attributeName, ns == "" ? null : ns);
            xn.Value = attributeValue;
            node.Attributes.SetNamedItem(xn);
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="node">节点对象</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attps">节点属性参数</param>
        public static void AddAttribute(this XmlDocument xDoc, XmlNode node, string namespaceOfPrefix, params AttributeParameter[] attps)
        {
            string ns = namespaceOfPrefix == null ? null : node.GetNamespaceOfPrefix(namespaceOfPrefix);
            foreach (AttributeParameter attp in attps)
            {
                XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns);
                xn.Value = attp.Value;
                node.Attributes.SetNamedItem(xn);
            }
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="node">节点对象</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attributeName">新属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void AddAttribute(string fileFullName, XmlNode node, string namespaceOfPrefix, string attributeName, string attributeValue)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            AddAttribute(xDoc, node, namespaceOfPrefix, attributeName, attributeValue);
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="node">节点对象</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attps">节点属性参数</param>
        public static void AddAttribute(string fileFullName, XmlNode node, string namespaceOfPrefix, params AttributeParameter[] attps)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            AddAttribute(xDoc, node, namespaceOfPrefix, attps);
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attributeName">新属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void AddAttribute(this XmlDocument xDoc, string nodeName, string namespaceOfPrefix, string attributeName, string attributeValue)
        {
            XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
            for (int i = 0; i < xlst.Count; i++)
            {
                XmlNode node = GetNode(xlst[i], nodeName);
                if (node == null) return;
                string ns = namespaceOfPrefix == null ? null : node.GetNamespaceOfPrefix(namespaceOfPrefix);
                XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attributeName, ns == "" ? null : ns);
                xn.Value = attributeValue;
                node.Attributes.SetNamedItem(xn);
            }
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attps">节点属性参数</param>
        public static void AddAttribute(this XmlDocument xDoc, string nodeName, string namespaceOfPrefix, params AttributeParameter[] attps)
        {
            XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
            for (int i = 0; i < xlst.Count; i++)
            {
                XmlNode node = GetNode(xlst[i], nodeName);
                if (node == null) return;
                string ns = namespaceOfPrefix == null ? null : node.GetNamespaceOfPrefix(namespaceOfPrefix);
                foreach (AttributeParameter attp in attps)
                {
                    XmlNode xn = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns);
                    xn.Value = attp.Value;
                    node.Attributes.SetNamedItem(xn);
                }
            }
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attributeName">新属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void AddAttribute(string fileFullName, string nodeName, string namespaceOfPrefix, string attributeName, string attributeValue)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
            for (int i = 0; i < xlst.Count; i++)
            {
                XmlNode node = GetNode(xlst[i], nodeName);
                if (node == null) break;
                AddAttribute(xDoc, node, namespaceOfPrefix, attributeName, attributeValue);
            }
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 添加节点属性
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="namespaceOfPrefix">该节点的命名空间URI</param>
        /// <param name="attps">节点属性参数</param>
        public static void AddAttribute(string fileFullName, string nodeName, string namespaceOfPrefix, params AttributeParameter[] attps)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            XmlNodeList xlst = xDoc.DocumentElement.ChildNodes;
            for (int i = 0; i < xlst.Count; i++)
            {
                XmlNode node = GetNode(xlst[i], nodeName);
                if (node == null) break;
                AddAttribute(xDoc, node, namespaceOfPrefix, attps);
            }
            xDoc.Save(fileFullName);
        }
        #endregion

        #region GetNode
        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="nodeName">节点名称</param>
        /// <returns></returns>
        public static XmlNode GetNode(string fileFullName, string nodeName)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            return xDoc.GetNode(nodeName);
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <returns></returns>
        public static XmlNode GetNode(this XmlDocument xDoc, string nodeName)
        {
            if (xDoc.DocumentElement.Name == nodeName)
                return xDoc.DocumentElement;

            return xDoc.DocumentElement.GetNode(nodeName);
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <returns></returns>
        public static XmlNode GetNode(this XmlNode node, string nodeName)
        {
            foreach (XmlNode xn in node)
            {
                if (xn.Name.ToLower() == nodeName.ToLower())
                    return xn;
                else
                {
                    XmlNode tmp = GetNode(xn, nodeName);
                    if (tmp != null)
                        return tmp;
                }
            }
            return null;
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="xpar">XML参数</param>
        public static XmlNode GetNode(this XmlDocument xDoc, XmlParameter xpar)
        {
            return GetNode(xDoc, xpar.Name, xpar.InnerText);
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <param name="xpar">XML参数</param>
        public static XmlNode GetNode(this XmlNode node, XmlParameter xpar)
        {
            return GetNode(node, xpar.Name, node.InnerText);
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="innerText">节点内容</param>
        public static XmlNode GetNode(this XmlDocument xDoc, string nodeName, string innerText)
        {
            return xDoc.DocumentElement.GetNode(nodeName, innerText);
        }

        /// <summary>
        /// 获取指定节点名称的节点对象
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="innerText">节点内容</param>
        public static XmlNode GetNode(this XmlNode node, string nodeName, string innerText)
        {
            foreach (XmlNode xn in node)
            {
                if (xn.Name.ToLower() == nodeName.ToLower() && xn.InnerText == innerText)
                    return xn;
                else
                {
                    XmlNode tmp = GetNode(xn, nodeName, innerText);
                    if (tmp != null)
                        return tmp;
                }
            }
            return null;
        }
        #endregion

        #region UpdateNode
        /// <summary>
        /// 修改节点的内容
        /// </summary>
        /// <param name="node">修改的节点对象</param>
        /// <param name="para">XML参数对象</param>
        public static void UpdateNode(this XmlNode node, XmlParameter para)
        {
            if (node is null)
                return;

            node.InnerText = para.InnerText;
            if (para.Attributes?.Length > 0 && node.Attributes?.Count > 0)
            {
                XmlDocument xDoc = new XmlDocument();
                string ns = para.NamespaceOfPrefix == null ? "" : node.GetNamespaceOfPrefix(para.NamespaceOfPrefix);
                foreach (var item in para.Attributes)
                {
                    XmlNode attr = xDoc.CreateNode(XmlNodeType.Attribute, item.Name, ns == "" ? null : ns);
                    attr.Value = item.Value;
                    node.Attributes.SetNamedItem(attr);
                }
            }
        }
        #endregion

        #region DeleteNode
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="Index">节点索引</param>
        public static void DeleteNode(this XmlDocument xDoc, int Index)
        {
            XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
            nlst[Index].ParentNode.RemoveChild(nlst[Index]);
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="Index">节点索引</param>
        public static void DeleteNode(string fileFullName, int Index)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            DeleteNode(xDoc, Index);
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="xns">需要删除的节点对象</param>
        public static void DeleteNode(this XmlDocument xDoc, params XmlNode[] xns)
        {
            foreach (XmlNode xnl in xns)
            {
                foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes)
                {
                    if (xnl.Equals(xn))
                    {
                        xn.ParentNode.RemoveChild(xn);
                        break;
                    }
                }
            }
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="xns">需要删除的节点对象</param>
        public static void DeleteNode(string fileFullName, params XmlNode[] xns)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            DeleteNode(xDoc, xns);
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="nodeText">节点内容</param>
        public static void DeleteNode(this XmlDocument xDoc, string nodeName, string nodeText)
        {
            foreach (XmlNode xn in xDoc.DocumentElement.ChildNodes)
            {
                if (xn.Name == nodeName)
                {
                    if (xn.InnerText == nodeText)
                    {
                        xn.ParentNode.RemoveChild(xn);
                        return;
                    }
                }
                else
                {
                    XmlNode node = GetNode(xn, nodeName);
                    if (node != null && node.InnerText == nodeText)
                    {
                        node.ParentNode.ParentNode.RemoveChild(node.ParentNode);
                        return;
                    }
                }
            }
        }
        /// <summary>
        /// 删除节点
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="nodeName">节点名称</param>
        /// <param name="nodeText">节点内容</param>
        public static void DeleteNode(string fileFullName, string nodeName, string nodeText)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            DeleteNode(xDoc, nodeName, nodeText);
            xDoc.Save(fileFullName);
        }
        #endregion

        #region SetAttribute
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <param name="attps">属性参数</param>
        public static void SetAttribute(this XmlNode node, params AttributeParameter[] attps)
        {
            XmlElement xe = (XmlElement)node;
            foreach (AttributeParameter attp in attps)
            {
                xe.SetAttribute(attp.Name, attp.Value);
            }
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="node">节点对象</param>
        /// <param name="attributeName">属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void SetAttribute(this XmlNode node, string attributeName, string attributeValue)
        {
            XmlElement xe = (XmlElement)node;
            xe.SetAttribute(attributeName, attributeValue);
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="elem">元素对象</param>
        /// <param name="attps">属性参数</param>
        public static void SetAttribute(this XmlElement elem, params AttributeParameter[] attps)
        {
            foreach (AttributeParameter attp in attps)
            {
                elem.SetAttribute(attp.Name, attp.Value);
            }
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="elem">元素对象</param>
        /// <param name="attributeName">属性名称</param>
        /// <param name="attributeValue">属性值</param>
        public static void SetAttribute(this XmlElement elem, string attributeName, string attributeValue)
        {
            elem.SetAttribute(attributeName, attributeValue);
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="xpara">XML参数</param>
        /// <param name="attps">属性参数</param>
        public static void SetAttribute(this XmlDocument xDoc, XmlParameter xpara, params AttributeParameter[] attps)
        {
            XmlElement xe = (XmlElement)GetNode(xDoc, xpara);
            if (xe == null) return;
            SetAttribute(xe, attps);
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="xDoc">XmlDocument对象</param>
        /// <param name="xpara">XML参数</param>
        /// <param name="newValue">新属性值</param>
        public static void SetAttribute(this XmlDocument xDoc, XmlParameter xpara, string attributeName, string newValue)
        {
            XmlElement xe = (XmlElement)GetNode(xDoc, xpara);
            if (xe == null) return;
            SetAttribute(xe, attributeName, newValue);
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="xpara">XML参数</param>
        /// <param name="newValue">新属性值</param>
        public static void SetAttribute(string fileFullName, XmlParameter xpara, string attributeName, string newValue)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            SetAttribute(xDoc, xpara, attributeName, newValue);
            xDoc.Save(fileFullName);
        }
        /// <summary>
        /// 修改属性值
        /// </summary>
        /// <param name="fileFullName">文件名称，包括完整路径</param>
        /// <param name="xpara">XML参数</param>
        /// <param name="attps">属性参数</param>
        public static void SetAttribute(string fileFullName, XmlParameter xpara, params AttributeParameter[] attps)
        {
            XmlDocument xDoc = OpenXml(fileFullName);
            SetAttribute(xDoc, xpara, attps);
            xDoc.Save(fileFullName);
        }
        #endregion

        #region 反序列化
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="xml">XML字符串</param>
        /// <returns></returns>
        public static T Deserialize<T>(string xml) where T : class, new()
        {
            try
            {
                using (StringReader sr = new StringReader(xml))
                {
                    XmlSerializer xmldes = new XmlSerializer(typeof(T));
                    return xmldes.Deserialize(sr) as T;
                }
            }
            catch (Exception e)
            {
                return null;
            }
        }
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <param name="type"></param>
        /// <param name="xml"></param>
        /// <returns></returns>
        public static T Deserialize<T>(Stream stream) where T : class, new()
        {
            XmlSerializer xmldes = new XmlSerializer(typeof(T));
            return xmldes.Deserialize(stream) as T;
        }
        #endregion

        #region 序列化
        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="type">类型</param>
        /// <param name="obj">对象</param>
        /// <returns></returns>
        public static string Serializer<T>(object obj) where T : class, new()
        {
            MemoryStream Stream = new MemoryStream();
            XmlSerializer xml = new XmlSerializer(typeof(T));
            try
            {
                //序列化对象
                xml.Serialize(Stream, obj);
            }
            catch (InvalidOperationException)
            {
                throw;
            }
            Stream.Position = 0;
            StreamReader sr = new StreamReader(Stream);
            string str = sr.ReadToEnd();

            sr.Dispose();
            Stream.Dispose();

            return str;
        }

        #endregion

        #region private AppendChild
        private static void AppendChild(this XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] paras)
        {
            foreach (XmlParameter xpar in paras)
            {
                XmlNode newNode = xDoc.CreateNode(XmlNodeType.Element, xpar.Name, null);
                string ns = xpar.NamespaceOfPrefix == null ? "" : newNode.GetNamespaceOfPrefix(xpar.NamespaceOfPrefix);
                if (xpar.Attributes?.Length > 0)
                {
                    foreach (AttributeParameter attp in xpar.Attributes)
                    {
                        XmlNode attr = xDoc.CreateNode(XmlNodeType.Attribute, attp.Name, ns == "" ? null : ns);
                        attr.Value = attp.Value;
                        newNode.Attributes.SetNamedItem(attr);
                    }
                }
                newNode.InnerText = xpar.InnerText;
                parentNode.AppendChild(newNode);
            }
        }
        #endregion

        #region private AddEveryNode
        private static void AddEveryNode(this XmlDocument xDoc, XmlNode parentNode, params XmlParameter[] paras)
        {
            XmlNodeList nlst = xDoc.DocumentElement.ChildNodes;
            foreach (XmlNode xns in nlst)
            {
                if (xns.Name == parentNode.Name)
                {
                    AppendChild(xDoc, xns, paras);
                }
                else
                {
                    foreach (XmlNode xn in xns)
                    {
                        if (xn.Name == parentNode.Name)
                        {
                            AppendChild(xDoc, xn, paras);
                        }
                    }
                }
            }
        }
        #endregion
    }

    public sealed class XmlParameter
    {
        private string name;
        private string innerText;
        private string namespaceOfPrefix;
        private AttributeParameter[] attributes;

        public XmlParameter()
        {
            //
            // TODO: Add constructor logic here
            //
            namespaceOfPrefix = null;
        }

        public XmlParameter(string name, params AttributeParameter[] attParas)
        {
            this.name = name;
            namespaceOfPrefix = null;
            attributes = attParas;
        }


        public XmlParameter(string name, string innerText, params AttributeParameter[] attParas)
        {
            this.name = name;
            this.innerText = innerText;
            namespaceOfPrefix = null;
            attributes = attParas;
        }

        public XmlParameter(string name, string innerText, string namespaceOfPrefix, params AttributeParameter[] attParas)
        {
            this.name = name;
            this.innerText = innerText;
            this.namespaceOfPrefix = namespaceOfPrefix;
            attributes = attParas;
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        public string InnerText
        {
            get { return innerText; }
            set { innerText = value; }
        }

        public string NamespaceOfPrefix
        {
            get { return namespaceOfPrefix; }
            set { namespaceOfPrefix = value; }
        }

        public AttributeParameter[] Attributes
        {
            get { return attributes; }
            set { attributes = value; }
        }
    }

    public sealed class AttributeParameter
    {
        private string name;
        private string value;

        public AttributeParameter()
        {
            //
            // TODO: Add constructor logic here
            //
        }
        public AttributeParameter(string attributeName, string attributeValue)
        {
            name = attributeName;
            value = attributeValue;
        }
        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        public string Value
        {
            get { return value; }
            set { this.value = value; }
        }

    }
}
